#include "key_drv.h"
#include "systick.h"

static Key_Info_t g_keyInfo[KEY_NUM_MAX];

static void GpioInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // GPIOB时钟使能
    RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_GPIOB, ENABLE);

    // PB02 -- key1
    GPIO_InitStructure.Pins = GPIO_PIN_2;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
    GPIO_InitStructure.IT = GPIO_IT_FALLING;
    GPIO_Init(CW_GPIOB, &GPIO_InitStructure);

    // PB03 -- key2
    GPIO_InitStructure.Pins = GPIO_PIN_3;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
    GPIO_InitStructure.IT = GPIO_IT_FALLING;
    GPIO_Init(CW_GPIOB, &GPIO_InitStructure);

    // PB04 -- key3
    GPIO_InitStructure.Pins = GPIO_PIN_4;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
    GPIO_InitStructure.IT = GPIO_IT_FALLING;
    GPIO_Init(CW_GPIOB, &GPIO_InitStructure);

    // PB05 -- key4
    GPIO_InitStructure.Pins = GPIO_PIN_5;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
    GPIO_InitStructure.IT = GPIO_IT_FALLING;
    GPIO_Init(CW_GPIOB, &GPIO_InitStructure);
}

/**
 * @brief 按键硬件初始化
 * @param
 * @return
 */
void KeyDrvInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    for (uint8_t i = 0; i < KEY_NUM_MAX; i++)
    {
        RCC_AHBPeriphClk_Enable(g_gpioList[i].rcc, ENABLE);
        GPIO_InitStructure.Pins = g_gpioList[i].pin;
        GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
        GPIO_InitStructure.IT = GPIO_IT_FALLING;
        GPIO_Init(g_gpioList[i].gpio, &GPIO_InitStructure);
    }
}

static uint8_t KeyScan(uint8_t keyIndex)
{
    volatile uint64_t curSysTime;
    uint8_t keyPress;

    keyPress = GPIO_ReadPin(g_gpioList[keyIndex].gpio, g_gpioList[keyIndex].pin);

    switch (g_keyInfo[keyIndex].keyState)
    {
    case KEY_RELEASE:  // 释放状态，判断有无按键按下
        if (!keyPress) // 有按键按下
        {
            g_keyInfo[keyIndex].keyState = KEY_CONFIRM;
            g_keyInfo[keyIndex].firstIoChangeSysTime = GetSysRunTime();
            break;
        }
        if (g_keyInfo[keyIndex].singleClickNum != 0)
        {
            curSysTime = GetSysRunTime();
            if (curSysTime - g_keyInfo[keyIndex].firstIoChangeSysTime > DOUBLE_CLICK_INTERVAL_TIME)
            {
                g_keyInfo[keyIndex].singleClickNum = 0;
                return (keyIndex + 0x01); // 返回单击按键码值，四个按键短按对应0x01, 0x02, 0x03, 0x04
            }
        }

        break;

    case KEY_CONFIRM:
        if (!keyPress)
        {
            curSysTime = GetSysRunTime();
            if (curSysTime - g_keyInfo[keyIndex].firstIoChangeSysTime > CONFIRM_TIME)
            {
                g_keyInfo[keyIndex].keyState = KEY_SHORTPRESS;
            }
        }
        else
        {
            g_keyInfo[keyIndex].keyState = KEY_RELEASE;
        }
        break;

    case KEY_SHORTPRESS: // 短按状态：继续判定是短按，还是双击，还是长按
        if (keyPress)
        {
            g_keyInfo[keyIndex].keyState = KEY_RELEASE;

            g_keyInfo[keyIndex].singleClickNum++;
            if (g_keyInfo[keyIndex].singleClickNum == 1)
            {
                g_keyInfo[keyIndex].firstReleaseSysTime = GetSysRunTime();
                break;
            }
            else
            {
                curSysTime = GetSysRunTime();
                if (curSysTime - g_keyInfo[keyIndex].firstReleaseSysTime <= DOUBLE_CLICK_INTERVAL_TIME) // 超过双击时间间隔窗，返回双击码值
                {
                    g_keyInfo[keyIndex].singleClickNum = 0;
                    return (keyIndex + 0x51); // 返回按键码值，四个按键双击对应0x51, 0x52, 0x53, 0x54
                }
            }
        }
        else
        {
            curSysTime = GetSysRunTime();
            if (curSysTime - g_keyInfo[keyIndex].firstIoChangeSysTime > LONGPRESS_TIME)
            {
                g_keyInfo[keyIndex].keyState = KEY_LONGPRESS;
            }
        }
        break;
    case KEY_LONGPRESS:
        if (keyPress)
        {
            g_keyInfo[keyIndex].keyState = KEY_RELEASE;
            return (keyIndex + 0x81); // 返回按键码值，四个按键长按对应0x81, 0x82, 0x83, 0x84
        }
        break;

    default:
        g_keyInfo[keyIndex].keyState = KEY_RELEASE;
        break;
    }
    return 0;
}

/**
 * @brief 获取按键码值
 * @param
 * @return 四个按键码值，短按0x01 0x02 0x03 0x04
 *                      双击0x51 0x52 0x53 0x54
 *                      长按0x81 0x82 0x83 0x84,没有按下为0
 */
uint8_t GetKeyVal(void)
{
    uint8_t res = 0;

    for (uint8_t i = 0; i < KEY_NUM_MAX; i++)
    {
        res = KeyScan(i);
        if (res != 0)
        {
            break;
        }
    }
    return res;
}

/**
 * @brief 按键测试
 * @param  
 */
void KeyDrvTest(void)
{
    static uint8_t i = 0;
    uint8_t keyVal = GetKeyVal();
    switch (keyVal)
    {
    case KEY1_SHORT_PRESS:
        i++;
        // printf("key1 short press\n");
        break;
    case KEY2_SHORT_PRESS:
        i++;
        // printf("key2 short press\n");
        break;
    case KEY3_SHORT_PRESS:
        i++;
        // printf("key3 short press\n");
        break;
    case KEY4_SHORT_PRESS:
        i++;
        // printf("key4 short press\n");
        break;
    case KEY1_DOUBLE_PRESS:
        i++;
        // printf("key1 double press\n");
        break;
    case KEY2_DOUBLE_PRESS:
        i++;
        // printf("key2 double press\n");
        break;
    case KEY3_DOUBLE_PRESS:
        i++;
        // printf("key3 double press\n");
        break;
    case KEY4_DOUBLE_PRESS:
        i++;
        // printf("key4 double press\n");
        break;
    case KEY1_LONG_PRESS:
        i++;
        // printf("key1 long press\n");
        break;
    case KEY2_LONG_PRESS:
        i++;
        // printf("key2 long press\n");
        break;
    case KEY3_LONG_PRESS:
        i++;
        // printf("key3 long press\n");
        break;
    case KEY4_LONG_PRESS:
        i++;
        // printf("key4 long press\n");
        break;
    default:
        break;
    }
}
